package com.qikux.controller;

import cn.hutool.core.io.FileUtil;
import com.qikux.annotation.*;
import com.qikux.annotition.Authentication;
import com.qikux.consts.AppConst;
import com.qikux.entity.User;
import com.qikux.entity.UserInfo;
import com.qikux.listener.UserManager;
import com.qikux.service.UserService;
import com.qikux.utils.*;
import com.qikux.vo.HttpEntity;
import com.qikux.vo.Page;
import com.qikux.vo.ResultVo;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.File;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

@Component
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    String pt = this.getClass().getResource("/").getPath().replaceFirst("/", "");
    String webappRoot = pt.replaceAll("target/downloadLover-1.0-SNAPSHOT/WEB-INF/classes/", "src/main/webapp/upload");
    /**
     * 1、跳转到注册页面
     * @return
     */
    @RequestMapping(value = "/register", method = RequestMethod.GET)
    public String register() {
       return "register";
    }

    @RequestMapping(value = "/register",method = RequestMethod.POST)
    public String register(HttpServletRequest request){
        // 接收页面参数
        String tel = request.getParameter("tel");
        String password = request.getParameter("password");
        String email = request.getParameter("email");

        // 2.调用业务逻辑层处理注册业务
        User user = User.builder()
                .tel(tel)
                .password(password)
                .email(email)
                .build();
        ResultVo<?> resultVo = userService.register(user);

        // 3.注册失败, 则 跳转到 注册页面
        if (!resultVo.isStatus()){
            // 设置失败的原因
            request.setAttribute(String.valueOf(resultVo.getData()),resultVo.getMessage());

            request.setAttribute("user",user);
            // 跳回注册页面
            return "register";
        }

        String message = "u=" +user.getId();
        String sign = RSAUtils.sign(message);
        // 如果注册成功,跳转到第二步
        return "redirect:/user/next?u=" + user.getId() + "&sign=" + sign;
    }

    @RequestMapping(value = "/next",method = {RequestMethod.POST,RequestMethod.GET})
    public String next(HttpServletRequest request){
        String uid = request.getParameter("u");
        String sign = request.getParameter("sign");
        String message = "u=" + uid ;
        if (!RSAUtils.verify(message,sign)){
            return "fail";
        }
        request.setAttribute("u",uid);
        return "next";
    }
    @RequestMapping(value = "/next/reg",method = RequestMethod.POST)
    public String nextReg(HttpServletRequest request ) throws Exception{
        // 接收页面传入的数据
        Part photo = request.getPart("photo");
        // 接收出生日期
        String birth = request.getParameter("birth");
        // 昵称
        String nickName = request.getParameter("nickname");
        // 真实姓名
        String realName = request.getParameter("realname");
        // 性别
        String sex = request.getParameter("sex");
        // 用户ID
        String userId = request.getParameter("userId");

        /*String pt = this.getClass().getResource("/").getPath().replaceFirst("/", "");

        String webappRoot = pt.replaceAll("target/downloadLover-1.0-SNAPSHOT/WEB-INF/classes/", "src/main/webapp/upload");
        System.out.println(webappRoot);*/

        String path = null;
        if (photo.getSize() > 0){
            //path = UploadUtils.upload(photo,"upload.photo.dir");
            path = UploadUtils.upload(photo,webappRoot);
        }

        nickName = "".equals(nickName) ? NicknameUtils.generatorNickName() : nickName;

        // 组装数据
        UserInfo userInfo = UserInfo
                .builder()
                .photo(path)
                .birth("".equals(birth) ? null : LocalDate.parse(birth,DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                .realName(realName)
                .sex(sex)
                .userId(Long.parseLong(userId))
                .nickName(nickName)
                .build();

        // 3.调用业务逻辑层处理业务
        ResultVo<User> resultVo = userService.saveUserInfo(userInfo);
        // 如果信息保存失败
        if (!resultVo.isStatus()){
            if (path != null) UploadUtils.delete(webappRoot,path);
            // 数据回显
            request.setAttribute("userInfo",userInfo);
            request.setAttribute("msg",resultVo.getMessage());
            // 跳回第二步
            return "forward:/user/next?u="+ userId;
        }

        User user = resultVo.getData();

        SendMailUtils.sendMailForActiveAccount(user.getTel(),user.getId(),user.getEmail());

        // 将返回到成功页面的消息做数字签名,防止篡改
        String message = "n=" + nickName + "&u=" + userId + "&e=" + user.getEmail();
        String sign = RSAUtils.sign(message);

        // 如果成功, 跳转到第三步
        return "redirect:/user/success?n=" + nickName + "&u=" + userId + "&e=" + user.getEmail() + "&sign=" + sign;
    }

    @RequestMapping(value = "/success",method = RequestMethod.GET)
    public String success(HttpServletRequest request){
        // 接受页面参数
        String n = request.getParameter("n");
        String u = request.getParameter("u");
        String e = request.getParameter("e");
        String sign = request.getParameter("sign");
        // 拼接要认证的字符串
        String message = "n=" + n + "&u=" + u + "&e=" + e;
        if (!RSAUtils.verify(message,sign)){
            request.setAttribute("errorMsg","数据认证失败、请勿篡改数据");
            return "fail";
        }
        return "success";
    }

    @RequestMapping(value = "/active",method = RequestMethod.GET)
    public String active(HttpServletRequest request, HttpServletResponse response) throws Exception{
        // 获取激活的 u,t和 sign
        String userId = request.getParameter("u");
        String time = request.getParameter("t");

        /**
         * sign 在 网络传输的过程中,如果 内容中包含 + , 会被浏览器自动替换成 空格
         *      解决方法
         *              1.  将 空格 替换成 +
         *              2.  sign 在网络传输前 ,在进行一次 URLEncode 编码
         *
         */

        String sign = request.getParameter("sign");

        // 判断 链接是否过期
        LocalDateTime activeTime = LocalDateTime.parse(time, DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));

        // 如果激活时间 小于 当前系统时间, 说明过期了
        if (LocalDateTime.now().isAfter(activeTime)){
            request.setAttribute("errorMsg","链接已失效");
            return "fail";
        }

        // 如果没有过期, 则 数字认证
        String message = "u=" + userId + "&t=" + time;
        if (!RSAUtils.verify(message,sign)){
            request.setAttribute("errorMsg","激活失败,请不要尝试篡改数据");
            return "fail";
        }

        // 如果认证成功,调用业务逻辑层 处理业务
        userService.activeAccount(Long.parseLong(userId));

        // 引导用户跳转到登录页面
        return "redirect:/user/login";
    }

    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public String login(HttpServletRequest request){
        // 在request作用域中,存储一个标记登录 页面的变量
        request.setAttribute("loginPage",true);

        // 从 session 获取 错误消息
        Object msg = request.getSession().getAttribute("msg");

        // 如果msg不为空,则将msg从session移除
        if (msg != null){
            request.getSession().removeAttribute("msg");
            request.setAttribute("msg",msg);
        }
        return "index";
    }

    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String loginSubmit(HttpServletRequest request){
        // 1.获取页面传入的 手机号 和 密码
        String tel = request.getParameter("tel");
        String password = request.getParameter("password");
        String redirectUrl = request.getParameter("url");

        // 登录成功、将 用户和 session绑定
        String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
                + request.getContextPath() + "/user/active";

        // 2. 调用业务逻辑层处理业务
        ResultVo<User> resultVo = userService.login(tel, password, url);
        // 调用业务逻辑层处理业务
//        ResultVo<User> resultVo = userService.login(tel,password);

        if (!resultVo.isStatus()){
            // 使用session 将 错误消息 传给 登录
            request.getSession().setAttribute("msg",resultVo.getMessage());

            if (redirectUrl != null && !"".equals(redirectUrl)){
                return "redirect:/user/login?url=" + URLEncoder.encode(redirectUrl, StandardCharsets.UTF_8);
            }
            return "redirect:/user/login";
        }

        // 3. 判断当前用户是否已经在线 ， 如果在线，则提示 当前账户已在其它地方登录
        UserManager userManager = (UserManager) ContextUtils.getApplication().getAttribute(AppConst.USER_MANAGER);

        // 如果在线，则提示 当前账户已在其它地方登录
        if (userManager.isOnline(resultVo.getData(), ContextUtils.getSession())) {
//            request.getSession().setAttribute("msg", "当前账户已在其它地方登录");
//            return "redirect:/user/login";
//            userManager.offLine(resultVo.getData()) ;
            userManager.offLine(resultVo.getData()) ;
        }

        // 登录成功、 将 用户 和 session 绑定

        // 写入用户登录标记
        request.getSession().setAttribute(AppConst.LOGIN_FLAG,resultVo.getData());

        // 将当前登录的用户写入到 session中
//         userManager.addUser(resultVo.getData(), ContextUtils.getSession());

        if (redirectUrl != null && !"".equals(redirectUrl)){
            return "redirect:" + redirectUrl;
        }
        // 如果成功, 则跳转到 系统 首页
        return "redirect:/index";
    }

    /**
     * 显示当前登录的用户头像
     * @param request
     * @return
     */
    @Authentication
    @RequestMapping("/photo")
    public HttpEntity showCurrentUserPhoto(HttpServletRequest request){
        // 获取 当前 登录的 用户 的头像 名字
        User user = (User) request.getSession().getAttribute(AppConst.LOGIN_FLAG);

        // 获取用户头像
        String photo = user.getInfo().getPhoto();

        File filePath = UploadUtils.findFile(webappRoot,photo);
        return new HttpEntity(FileUtil.readBytes(filePath), "", false);

    }

    /**
     * 修改当前登录的用户头像
     * @param
     * @return
     */
    @Authentication
    @RequestMapping(value = "/photo",method = RequestMethod.POST)
    @ResponseBody
    public ResultVo<String> updateCurrentUserPhoto() throws Exception{
        // 获取 当前 登录的 用户 的头像 名字
        User user = (User) ContextUtils.getSession().getAttribute(AppConst.LOGIN_FLAG);

        // 接收上传的头像
        Part photo = ContextUtils.getRequest().getPart("photo");

        // 上传头像到服务器
        String path = UploadUtils.upload(photo, webappRoot);

        // 将头像 存储到数据库中
        UserInfo info = UserInfo.builder().userId(user.getId()).photo(path).build();

        user.setInfo(info);
        // 调用业务逻辑层,修改头像
        return userService.updatePhoto(info);

    }


    @RequestMapping("/logout")
    public String logout(HttpServletRequest request){
        // session 默认存活时间30分钟
        // 退出登录, 将session 销毁

        // 设置 session 的 存活时间, 单位是秒
        //request.getSession().setMaxInactiveInterval(30*60);

        // 销毁 session
        request.getSession().invalidate();

        // 跳转到登录页面
        return "redirect:/user/login";
    }


    @RequestMapping(value = "/personal",method = RequestMethod.GET)
    public String personal(){
        return "personal";
    }

    /**
     * 统计积分的来源
     */
    @Authentication
    @RequestMapping(value = "/statics/score",method = RequestMethod.GET)
    @ResponseBody
    public ResultVo<List<Map<String,Object>>> staticsScore(){

        User user = (User) ContextUtils.getRequest().getSession().getAttribute(AppConst.LOGIN_FLAG);

        Long userId = user.getId();

        // 调用业务逻辑层、查询 统计的积分信息
        return userService.staticsScore(userId);
    }

    @Authentication
    @RequestMapping(value = "/detail/score",method = RequestMethod.GET)
    @ResponseBody
    public ResultVo<Page<Map<String, Object>>> detailScore(){
        // 获取当前登录的用户信息
        User user = (User) ContextUtils.getSession().getAttribute(AppConst.LOGIN_FLAG);

        Long userId = user.getId();

        // 分页查询, 获取页码
        String page = ContextUtils.getRequest().getParameter("page");
        if (page == null || "".equals(page)) page = "1";
        int _page = Integer.parseInt(page);

        /**
         * 包含了分页参数
         */
        Page<Map<String,Object>> pageBean = Page.builder().page(_page).build();
        // 调用业务逻辑层处理业务
        return userService.detailScore(userId,pageBean);
    }

    /**
     * @description 跳转收藏页面
     * @date 2022/9/26 21:18
     * @auther XuHuanDong
     */
    @RequestMapping(value = "/shoucang" ,method = RequestMethod.GET)
    public String collect(){
        return "shoucang";
    }

    /**
     * @description 收藏资源api
     * @param
     * @return com.qikux.vo.ResultVo<java.util.List<java.util.Map<java.lang.String,java.lang.Object>>>
     * @date 2022/9/27 9:16
     * @auther XuHuanDong
     */
    @RequestMapping(value = "/collectMsg")
    @ResponseBody
    @Authentication
    public ResultVo<Page<Map<String, Object>>> collectMsg(){
        //获取当前登录用户信息
        User user = (User) ContextUtils.getSession().getAttribute(AppConst.LOGIN_FLAG);
        // 分页查询, 获取页码
        String page = ContextUtils.getRequest().getParameter("page");
        if (page == null || "".equals(page)) page = "1";
        int _page = Integer.parseInt(page);

        //包含了分页参数
        Page<Map<String,Object>> pageBean = Page.builder().page(_page).rows(3).build();
        //调用业务层处理
        return userService.findCollect(user,pageBean);
    }

    @Authentication
    @RequestMapping(value = "/more",method = RequestMethod.GET)
    public String moreReslt(HttpServletRequest request){
        return "more";
    }


    @RequestMapping(value = "/resMsg")
    @ResponseBody
    @Authentication
    public ResultVo<Page<Map<String, Object>>> resMsg(HttpServletRequest request){
        //获取当前登录用户信息
       Long userId = Long.parseLong(request.getParameter("resUserId"));
        //System.out.println(userId);
        //User user = (User) ContextUtils.getSession().getAttribute(AppConst.LOGIN_FLAG);
        // 分页查询, 获取页码
        String page = ContextUtils.getRequest().getParameter("page");
        if (page == null || "".equals(page)) page = "1";
        int _page = Integer.parseInt(page);

        //包含了分页参数
        Page<Map<String,Object>> pageBean = Page.builder().page(_page).rows(3).build();
        //调用业务层处理
        return userService.findCol(userId,pageBean);
    }

}
